/**
* @file data_redis.hpp
* @author zhaobohan (zhaobohan_free@163.com)
* @brief 对于Redis数据的封装操作
*/

#include <sw/redis++/redis.h>

namespace free_im 
{
// 工厂用于创建Redis的链接
class RedisClientFactory 
{
public:
    static std::shared_ptr<sw::redis::Redis> create(
        const std::string &host,
        int port,
        int db,
        bool keep_alive)
    {
        sw::redis::ConnectionOptions opts;
        opts.host = host;
        opts.port = port;
        opts.db = db;
        opts.keep_alive = keep_alive;
        auto res = std::make_shared<sw::redis::Redis>(opts);
        return res;
    }
};

// 利用Redis来维持会话关系
class Session 
{
public:
    using ptr = std::shared_ptr<Session>;
    Session(const std::shared_ptr<sw::redis::Redis> &redis_client)
        : _redis_client(redis_client)
    {}

    // 绑定sessionID和userID的映射关系
    void append(const std::string &ssid, const std::string &uid) 
    {
        _redis_client->set(ssid, uid);
    }

    // 移除映射关系
    void remove(const std::string &ssid) 
    {
        _redis_client->del(ssid);
    }

    // 根据sessionID获取userID
    sw::redis::OptionalString uid(const std::string &ssid) 
    {
        return _redis_client->get(ssid);
    }

private:
    std::shared_ptr<sw::redis::Redis> _redis_client;
};

// 校验用户登录状态
class Status 
{
public:
    using ptr = std::shared_ptr<Status>;
    Status(const std::shared_ptr<sw::redis::Redis> &redis_client)
        : _redis_client(redis_client)
    {}

    // 如果用户登录了就设置一下userID和空值的映射关系
    void append(const std::string &uid) 
    {
        _redis_client->set(uid, "");
    }

    // 移除用户登录状态
    void remove(const std::string &uid) 
    {
        _redis_client->del(uid);
    }

    // 判断该用户登录状态是否存在
    bool exists(const std::string &uid) 
    {
        auto res = _redis_client->get(uid);
        if (res) return true;
        return false;
    }

private:
    std::shared_ptr<sw::redis::Redis> _redis_client;
};

// 对于登录验证码的校验逻辑
class Codes 
{
public:
    using ptr = std::shared_ptr<Codes>;
    Codes(const std::shared_ptr<sw::redis::Redis> &redis_client)
        : _redis_client(redis_client)
    {}

    // 插入一条验证码，设置过期时间为300秒
    void append(const std::string &cid, const std::string &code, 
        const std::chrono::milliseconds &t = std::chrono::milliseconds(300 * 1000)) 
    {
        _redis_client->set(cid, code, t);
    }

    // 手动移除指定的验证码
    void remove(const std::string &cid) 
    {
        _redis_client->del(cid);
    }

    // 根据ID获取验证码
    sw::redis::OptionalString code(const std::string &cid)  
    {
        return _redis_client->get(cid);
    }

private:
    std::shared_ptr<sw::redis::Redis> _redis_client;
};
}